
package managementClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import billingServer.Bill;
import billingServer.PriceSteps;

import common.BidEvent;
import common.RegistryManagement;
import common.rmi.ClientReference;
import common.rmi.RemoteAnalyzer;
import common.rmi.RemoteBillingServer;
import common.rmi.RemoteBillingServerSecure;

public class ManagementClient extends UnicastRemoteObject implements ClientReference {
	private static final long serialVersionUID = 1L;

	private boolean auto;
	private Vector<String> notifications;
	
	public ManagementClient() throws RemoteException{
		super(0);
		this.notifications=new Vector<String>();
		this.auto=false;
	}
	public static void main(String [] args){
		System.out.println("Management client is running");
		
		String userLine="";
		String command="";
		StringBuilder registryHost = new StringBuilder(); 
		StringBuilder registryPortStr = new StringBuilder(); 
		RegistryManagement.getRegistryInfo(registryHost, registryPortStr);
		int registryPort = Integer.valueOf(registryPortStr.toString());
		
		String analyticsServerBindingName = args[0];
		String billingServerBindingName = args[1];
		
		try
		{
			ManagementClient client = new ManagementClient();
			
			BufferedReader reader= new BufferedReader(new InputStreamReader(System.in));
			Scanner stringReader;
			
			Timer timer=new Timer();
			timer.schedule(client.newTask() ,0, 1*1000);
			
			String addressRMI = "rmi://" + registryHost.toString() + ":" + String.valueOf(registryPort) + "/";
			RemoteAnalyzer analyticsServer=(RemoteAnalyzer)Naming.lookup(addressRMI + analyticsServerBindingName);
			RemoteBillingServer billingServer=(RemoteBillingServer)Naming.lookup(addressRMI + billingServerBindingName);
			
			RemoteBillingServerSecure billingServerSecure = null;
			while(true){
				try {
					userLine=reader.readLine();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				
				stringReader=new Scanner(userLine);
				try{
					command=stringReader.next();
				}catch(java.util.NoSuchElementException e){
					System.out.println("Please enter a command starting with!");
				}

				try {
					if(command.equals("!login")){
						if (billingServerSecure == null)
						{
							String userName;
							String password;
							try{
								userName=stringReader.next();				
								try{
									password=stringReader.next();
									billingServerSecure = billingServer.login(userName, password);
									System.out.println(userName + " successfully logged in");
								}catch(java.util.NoSuchElementException e){
									System.out.println("ERROR: please enter your password!");
								}
							}catch(java.util.NoSuchElementException e){
								System.out.println("ERROR: please enter a user name!");
							}
						}
						else
						{
							System.out.println("ERROR: you have logged on before!");
						}
					}
					else if(command.equals("!addStep")){
						if (billingServerSecure != null)
						{
							double startPrice;
							double endPrice;
							double fixedPrice;
							double variablePricePercent;
							try{
								startPrice = Double.valueOf(stringReader.next());				
								try{
									endPrice = Double.valueOf(stringReader.next());
									try{
										fixedPrice = Double.valueOf(stringReader.next());
										try{
											variablePricePercent = Double.valueOf(stringReader.next());
											billingServerSecure.createPriceStep(startPrice, endPrice, fixedPrice, variablePricePercent);
											
											String endPriceMessage = String.valueOf(endPrice);
											if (endPrice == 0)
												endPriceMessage = "INFINITY";
											System.out.println("Step [" + String.valueOf(startPrice) + " " + endPriceMessage + "] successfully added");
										}catch(java.util.NoSuchElementException e){
											System.out.println("ERROR: please enter variablePricePercent!");
										}
									}catch(java.util.NoSuchElementException e){
										System.out.println("ERROR: please enter fixedPrice!");
									}
								}catch(java.util.NoSuchElementException e){
									System.out.println("ERROR: please enter endPrice!");
								}
							}catch(java.util.NoSuchElementException e){
								System.out.println("ERROR: please enter a startPrice!");
							}
						}
						else
						{
							System.out.println("ERROR: please log in!");
						}
							
					}
					else if(command.equals("!removeStep")){
						if (billingServerSecure != null)
						{
							double startPrice;
							double endPrice;
							try{
								startPrice = Double.valueOf(stringReader.next());				
								try{
									endPrice = Double.valueOf(stringReader.next());
									billingServerSecure.deletePriceStep(startPrice, endPrice);
									String endPriceMessage = String.valueOf(endPrice);
									if (endPrice == 0)
										endPriceMessage = "INFINITY";
									System.out.println("Step [" + String.valueOf(startPrice) + " " + endPriceMessage + "] successfully removed");
								}catch(java.util.NoSuchElementException e){
									System.out.println("ERROR: please enter endPrice!");
								}
							}catch(java.util.NoSuchElementException e){
								System.out.println("ERROR: please enter a startPrice!");
							}
						}
						else
						{
							System.out.println("ERROR: please log in!");
						}
					}
					else if(command.equals("!bill")){
						if (billingServerSecure != null)
						{
							String userNme;
							try{
								userNme = stringReader.next();
								Bill bill = billingServerSecure.getBill(userNme);
								System.out.println("AuctionID - StrikePrice - Fee_Fixed - Fee_Variable - Fee_Total");
								for (int i = 0; i < bill.data.size(); i++)
								{
									String printLine = String.valueOf(bill.data.get(i).AuctionID) + " - " +
													   String.valueOf(bill.data.get(i).AuctionPrice) + " - " +
													   String.valueOf(bill.data.get(i).CalculatedFixedPrice) + " - " +
													   String.valueOf(bill.data.get(i).CalculatedVariablePrice) + " - " +
													   String.valueOf(bill.data.get(i).CalculatedFixedPrice + bill.data.get(i).CalculatedVariablePrice);
									System.out.println(printLine);
								}
							}catch(java.util.NoSuchElementException e){
								System.out.println("ERROR: please enter user name!");
							}
						}
						else
						{
							System.out.println("ERROR: please log in!");
						}
					}
					else if(command.equals("!steps")){
						if (billingServerSecure != null)
						{
							PriceSteps priceSteps = billingServerSecure.getPriceSteps();
							System.out.println("Min_Price - Max_Price - Fee_Fixed - Fee_Variable");
							for (int i = 0; i < priceSteps.data.size(); i++)
							{
								String printLine = String.valueOf(priceSteps.data.get(i).MinPrice) + " - " +
												   String.valueOf(priceSteps.data.get(i).MaxPrice) + " - " +
												   String.valueOf(priceSteps.data.get(i).FixedPrice) + " - " +
												   String.valueOf(priceSteps.data.get(i).VariablePricePercent) + " %";
								System.out.println(printLine);
							}
						}
						else
						{
							System.out.println("ERROR: please log in!");
						}
					}
					else if(command.equals("!logout")){
						if (billingServerSecure != null)
						{
							billingServerSecure = null;
							System.out.println("User successfully logged out");
						}
						else
							System.out.println("ERROR: please log in!");
					}
					else if(command.equals("!subscribe")){
						try{
							String filter=stringReader.nextLine();
							String notification;
							try{
								notification=analyticsServer.subscribe(filter, client);
								System.out.println("Subscription with ID:"+notification+"has been created");
							}catch(Exception e){
								System.out.println("ERROR#M.C.001! :Connection problem with analytics server, remote method subscribe");
							}
						}catch(java.util.NoSuchElementException e){
							System.out.println("Please enter a filter for the subscription!\n" +
									"correct syntax: !subscribe (USER_.*)|(BID_.*)");
						}
					}
					else if(command.equals("!unsubscribe")){
						String subscriptionID=stringReader.next();
						
						try{
							String notification=analyticsServer.unsubscribe(subscriptionID);
							System.out.println(notification);
						}catch(Exception e){
							System.out.println("ERROR#M.C.002! :Connection problem with analytics server");
						}
					}else if(command.equals("!auto")){
						client.auto=true;
						System.out.println("Status changed to auto");
					}else if(command.equals("!hide")){
						client.auto=false;
						System.out.println("Status changed to hide");
					}else if(command.equals("!print")){
							
						for(int i=0;i<client.notifications.size();i++){
							System.out.println(client.notifications.get(i));
							//client.notifications.remove(i);
						}
						synchronized(client.notifications){client.notifications=new Vector<String>();
						}
					}else if(command.equals("!exit")){
							System.out.println(exit(client,timer));
							break;
					}else{
						System.out.println("Unknown Command or Syntax Error please make sure you provide the system \n" +
							"with known commands with the right Syntax: !<command> <optional parameter1> <optional parameter2>");
					}
				} catch (RemoteException e2) {
					if (e2.detail != null)
						System.out.println("ERROR: " + e2.detail.getMessage());
					else
						System.out.println("ERROR: " + e2.getMessage());
				}
			}
		} catch (MalformedURLException e2) {
			e2.printStackTrace();
		} catch (NotBoundException e2) {
			System.out.println("Cannot connect to Servers");
		} catch (RemoteException e2) {
			System.out.println("Error in connection");
		}
	}
	
	private static String exit(ManagementClient client, Timer timer){
		try {
			UnicastRemoteObject.unexportObject(client, true);
		} catch (NoSuchObjectException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		timer.cancel();
		return "Succesfully freed all resources";
	}
	@Override
	public void forwardEvent(String notification) {
		synchronized(this.notifications){
			this.notifications.add(notification);
		}
		
	}
	private NotificationTask newTask(){
		return new NotificationTask(this.notifications);
	}

	private class NotificationTask extends TimerTask{
		private Vector<String> notifications;
		
		private NotificationTask(Vector<String> notifications){
			this.notifications=notifications;
		}
		@Override
		public void run() {
			
			if(notifications.isEmpty()!=true&&auto){
				
					
					for(int i=0;i<notifications.size();i++){
						System.out.println(notifications.get(i));
					}
					synchronized(notifications){	
						notifications.clear();
				}
				}
			}
		}
	}



